<!-- 字段映射 -->
<template>
  <el-dialog
    :title="dialogTitle"
    :visible.sync="dialogVisible"
    width="50%"
    append-to-body
    custom-class="field-map-dialog"
  >
    <div class="field-map" :key="configKey">
      <div class="map-title">
        <div class="title-item">
          源头表名称: {{ dialogForm.sourceTableName }}
        </div>
        <div class="title-item">
          目标模型名称: {{ dialogForm.targetTableName }}
        </div>
      </div>
      <div class="map-wrap">
        <div class="field-box source">
          <div class="field-box-top">
            <div class="field-top-title">源字段</div>
          </div>
          <div class="field-box-main">
            <div
              v-for="(i, idx) in sourceFields"
              :key="i.columnName"
              class="field-item"
              :class="{ 'is-active': idx === sourceActiveIndex }"
              @click="changeActive(idx, 'source')"
            >
              {{ i.columnName }}&lt;{{ i.comment }}&gt;
            </div>
          </div>
        </div>
        <div class="field-box target">
          <div class="field-box-top">
            <div class="field-top-title">目标字段</div>
          </div>
          <div class="field-box-main">
            <div
              v-for="(j, idx) in targetFields"
              :key="j.columnName"
              class="field-item"
              :class="{ 'is-active': idx === targetActiveIndex }"
              @click="changeActive(idx, 'target')"
            >
              {{ j.columnName }}&lt;{{ j.comment }}&gt;
            </div>
          </div>
        </div>
        <div class="transfer-box">
          <el-button
            type="primary"
            size="small"
            :disabled="sourceActiveIndex === null || targetActiveIndex === null"
            @click="transferRight"
          >
            &gt;
          </el-button>
          <el-button
            type="primary"
            size="small"
            :disabled="resultActiveIndex === null"
            @click="transferLeft"
          >
            &lt;
          </el-button>
        </div>
        <div class="field-box result">
          <div class="field-box-top">
            <div class="field-top-title">映射结果</div>
            <div>
              <el-button type="primary" size="mini" @click="transferSameFields"
                >同名映射</el-button
              >
            </div>
          </div>
          <div class="field-box-main">
            <div
              v-for="(k, idx) in resultFields"
              :key="k.columnName"
              class="field-item"
              :class="{ 'is-active': idx === resultActiveIndex }"
              @click="changeActive(idx, 'result')"
            >
              {{ k[0].columnName }}&lt;{{ k[0].comment }}&gt;
              <i class="el-icon-sort"></i>
              {{ k[1].columnName }}&lt;{{ k[1].comment }}&gt;
            </div>
          </div>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" @click="confirmDialog">保存</el-button>
    </template>
  </el-dialog>
</template>
<script>
export default {
  name: "MapDialog",
  data() {
    return {
      configKey: 1,
      dialogTitle: "维护字段映射",
      dialogVisible: false,
      dialogForm: {},
      sourceFields: [],
      sourceActiveIndex: null,
      targetFields: [],
      targetActiveIndex: null,
      resultFields: [],
      resultActiveIndex: null,
    };
  },
  methods: {
    // 打开弹窗
    openDialog(info) {
      this.dialogForm = info;
      this.sourceFields = info.sourceFieldList || [];
      this.targetFields = info.targetFieldList || [];
      this.resultFields = info.resultFieldList || [];
      // 修改key
      this.configKey++;
      this.dialogVisible = true;
    },
    // 切换激活项
    changeActive(index, type) {
      switch (type) {
        case "target":
          this.targetActiveIndex =
            this.targetActiveIndex === index ? null : index;
          break;
        case "result":
          this.resultActiveIndex =
            this.resultActiveIndex === index ? null : index;
          break;
        default:
          this.sourceActiveIndex =
            this.sourceActiveIndex === index ? null : index;
          break;
      }
    },
    // 向右穿梭
    transferRight() {
      this.resultFields.push([
        this.sourceFields.splice(this.sourceActiveIndex, 1)[0],
        this.targetFields.splice(this.targetActiveIndex, 1)[0],
      ]);
      this.sourceActiveIndex = null;
      this.targetActiveIndex = null;
    },
    // 向左穿梭
    transferLeft() {
      let tmp = this.resultFields.splice(this.resultActiveIndex, 1)[0];
      this.sourceFields.push(tmp[0]);
      this.targetFields.push(tmp[1]);
      this.resultActiveIndex = null;
    },
    // 同名映射
    transferSameFields() {
      const sourceMap = new Map();
      // 转换源头表信息
      this.sourceFields.forEach((ele, index) => {
        sourceMap.set(ele.columnName, index);
      });
      // 存储同名的index
      let sourceIndexArr = [];
      let targetIndexArr = [];
      // 存储结果项
      let result = [];
      this.targetFields.forEach((ele, index) => {
        if (sourceMap.has(ele.columnName)) {
          // 存在同名key时 添加到映射结果
          let sourceIdx = sourceMap.get(ele.columnName);
          result.push([this.sourceFields[sourceIdx], this.targetFields[index]]);
          sourceIndexArr.push(sourceIdx);
          targetIndexArr.push(index);
        }
      });

      // 处理目标字段和原字段
      if (sourceIndexArr.length) {
        this.sourceFields = this.sourceFields.filter(
          (e, idx) => !sourceIndexArr.includes(idx)
        );
        this.targetFields = this.targetFields.filter(
          (e, idx) => !targetIndexArr.includes(idx)
        );
      }
      // 添加映射结果
      this.resultFields.push(...result);
    },
    confirmDialog() {
      this.$emit(
        "confirm",
        `${this.dialogForm.sourceTableName}^${this.dialogForm.targetModelId}`,
        this.resultFields
      );
      this.dialogVisible = false;
    },
  },
};
</script>

<style>
.field-map-dialog .el-dialog__body {
  padding: 10px 20px;
}
</style>
<style lang="scss" scoped>
.field-map {
  display: flex;
  flex-direction: column;
  height: 50vh;
  overflow: hidden;
}

.map-title {
  display: flex;
  padding: 10px 5px;
  border: 1px solid #e5e5e5;
  .title-item:not(:nth-last-child(1)) {
    margin-right: 20px;
  }
}

.map-wrap {
  flex: 1;
  overflow: hidden;
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
}

.field-box {
  display: flex;
  flex-direction: column;
  flex-grow: 0;
  flex-shrink: 0;
  overflow: hidden;
  &.source {
    flex-basis: 22%;
  }
  &.target {
    flex-basis: 22%;
  }
  &.result {
    flex-basis: 45%;
  }
}
.transfer-box {
  flex: 0 0 50px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /deep/ .el-button--primary {
    padding: 7px 10px;
    margin-bottom: 30px;
  }
  /deep/ .el-button + .el-button {
    margin: 0;
  }
}

.field-box-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.field-top-title {
  position: relative;
  padding: 10px 7px;
  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 3px;
    height: 12px;
    transform: translateY(-50%);
    background-color: $--color-primary;
  }
}

.field-box-main {
  flex: 1;
  overflow-y: auto;
  overflow-x: auto;
  padding: 10px 5px;
  border: 1px solid #e5e5e5;
  overflow-y: auto;
}

.field-item {
  box-sizing: border-box;
  width: max-content;
  padding: 5px;
  font-size: 14px;
  white-space: nowrap;
  cursor: pointer;
  &.is-active {
    background-color: #f1f4fd;
    color: $--color-primary;
  }
}

.el-icon-sort {
  transform: rotate(90deg);
  background-color: #a5b8f5;
}
</style>
